<?php

namespace app\utils\Service\Tencent;

use app\utils\CurlUtil;

class TencentIm extends Module
{
    private $config;
    private $host = "https://console.tim.qq.com";

    public function __construct()
    {
        // 获取配置信息
        $this->config = [
            'appid'      => config('tencent_im.sdkappid'),
            'identifier' => config('tencent_im.identifier'),
            'key'        => config('tencent_im.key'),
        ];
    }

    /**
     * 注册im
     * @param string $userid
     * @param string $nickname
     * @param string $avatar
     * @return bool
     */
    public function register(string $userid, string $nickname, string $avatar = '')
    {
        $data = [
            'UserID'  => $userid,
            'Nick'    => $nickname,
            'FaceUrl' => $avatar
        ];
        $res  = $this->postJson('/v4/im_open_login_svc/account_import', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }
        return $this->success('操作成功', $res);
    }

    /**
     * 设置用户资料
     * @param string $userid
     * @param array $params
     * @return bool
     */
    public function set_info(string $userid,array $params = [])
    {
        $data = [];
        foreach ($params as $key => $value) {
            $data[] = [
                'Tag'  => $key,
                'Value'  => $value,
            ];
        }
        $data = [
            'From_Account'  => $userid,
            'ProfileItem'    => $data
        ];
        $res  = $this->postJson('/v4/profile/portrait_set', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }
        return $this->success('操作成功', $res);
    }

    /**
     * 发送消息给某人
     * @param $from_user
     * @param $to_user
     * @param $message
     * @param $type //0普通消息 1自定义消息
     * @return bool
     */
    public function sendMessageToUser($from_user, $to_user, $message, $type = 0)
    {
        $data = [
            'SyncOtherMachine' => 1,
            'From_Account'     => (string)$from_user,
            'To_Account'       => (string)$to_user,
            'MsgRandom'        => rand(1000000, 9999999),
            'MsgTimeStamp'     => time(),
        ];
        if ($type == 1) { //自定义消息
            $body_message      = '{"businessID":"custom_tips_message","receiverShow":true,"senderId":"' . $from_user . '","text":"' . $message . '","tipType":257,"version":0}';
            $data["MsgBody"][] = [
                "MsgType"    => "TIMCustomElem",
                "MsgContent" => [
                    "Data"  => $body_message,
                    "Desc"  => $body_message,
                    "Ext"   => 'custom_tips_message',
                    "Sound" => ''
                ],
            ];
        } elseif ($type == 2) {
            // 完全自定义
            $data['MsgBody']         = $message['MsgBody'];
            $data['CloudCustomData'] = $message['CloudCustomData'];
        } elseif ($type == 3) {
            // 客服自定义消息
            $data["MsgBody"][] = [
                "MsgType"    => "TIMCustomElem",
                "MsgContent" => [
                    "Data"  => json_encode($message,JSON_UNESCAPED_UNICODE),
                    "Desc"  => json_encode($message,JSON_UNESCAPED_UNICODE),
                    "Ext"   => 'custom_tips_message',
                    "Sound" => ''
                ],
            ];
        } else {
            $data["MsgBody"][] = [
                "MsgType"    => "TIMTextElem",
                "MsgContent" => [
                    "Text" => $message
                ],
            ];
        }
        $res = $this->postJson('/v4/openim/sendmsg', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('操作成功', $res);
    }

    /**
     * 批量发送消息
     * @param $from_user
     * @param array $to_user
     * @param $message
     * @param $type //0普通消息 1自定义消息
     * @return bool
     */
    public function sendMessageToUsers($from_user, array $to_user, $message, $type = 0)
    {
        $data = [
            'SyncOtherMachine' => 2,
            'From_Account'     => (string)$from_user,
            'To_Account'       => $to_user,
            'MsgRandom'        => rand(1000000, 9999999),
            'MsgTimeStamp'     => time(),
        ];
        if ($type == 1) { //自定义消息
            $body_message      = '{"businessID":"custom_tips_message","receiverShow":true,"senderId":"' . $from_user . '","text":"' . $message . '","tipType":257,"version":0}';
            $data["MsgBody"][] = [
                "MsgType"    => "TIMCustomElem",
                "MsgContent" => [
                    "Data"  => $body_message,
                    "Desc"  => $body_message,
                    "Ext"   => 'custom_tips_message',
                    "Sound" => ''
                ],
            ];
        } elseif ($type == 2) {
            // 完全自定义
            $data['MsgBody']         = $message['MsgBody'];
            $data['CloudCustomData'] = $message['CloudCustomData'];
        } else {
            $data["MsgBody"][] = [
                "MsgType"    => "TIMTextElem",
                "MsgContent" => [
                    "Text" => $message
                ],
            ];
        }
        $res = $this->postJson('/v4/openim/sendmsg', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('操作成功', $res);
    }

    /**
     * 创建群组
     * @param $user_id
     * @param $room_no
     * @param $room_name
     * @param $type
     * @param $params // 其他参数
     * @return bool
     */
    public function create_group($user_id, $room_no, $room_name, $type = 'AVChatRoom', $params = [])
    {
        $this->config['identifier'] = (string)$user_id;// 群主 ID
        $data = [
            'Owner_Account' => (string)$user_id,        // 群主 ID
            'Type'          => $type,                   // 群组形态，包括 Public（陌生人社交群），Private（即 Work，好友工作群），ChatRoom（即 Meeting，会议群），AVChatRoom（直播群），Community（社群）
            'GroupId'       => (string)$room_no,        // 自定义群组 ID
            'Name'          => $room_name,

            // 申请加群处理方式。包含 FreeAccess（自由加入），NeedPermission（需要验证），DisableApply（禁止加群），如果不填，具体默认项可参见 加群方式差异；
            // 仅当创建支持申请加群的 群组 时，该字段有效。
            // 社群目前不支持此字段。
            //'ApplyJoinOption' => 'NeedPermission',// 申请加群处理方式。

            // 邀请加群处理方式，包含 FreeAccess （直接邀请用户进群，不需要审批等操作）， NeedPermission 需要群管理员或者群主审批， DisableInvite 不支持 SDK 邀请进群， 该选项 AVChatRoom 群类型不支持
            //'InviteJoinOption' => 'NeedPermission',// 申请加群处理方式。
        ];
        $res  = $this->postJson('/v4/group_open_http_svc/create_group', array_merge($data, $params));
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('创建成功', $res);
    }

    // 解散群组
    public function close_group($room_no)
    {
        $data = [
            'GroupId'       => (string)$room_no,        // 自定义群组 ID
        ];
        $res  = $this->postJson('/v4/group_open_http_svc/destroy_group', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('解散成功', $res);
    }

    /**
     * 创建群组
     * @param $user_id
     * @param $room_no
     * @param $room_name
     * @param $type
     * @param $params // 其他参数
     * @return bool
     */
    public function modify_group_base_info($room_no, $room_name, $face_url = '', $params = [])
    {
        $data = [
            'GroupId' => (string)$room_no,        // 自定义群组 ID
            'Name'    => $room_name,
            'FaceUrl' => $face_url,
        ];
        $res  = $this->postJson('/v4/group_open_http_svc/modify_group_base_info', array_merge($data, $params));
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('创建成功', $res);
    }

    // 发送群系统消息
    public function send_group_system_message($room_no,$content)
    {
        $data = [
            'GroupId' => (string)$room_no,        // 自定义群组 ID
            'Content' => $content,                // 消息内容
        ];
        $res  = $this->postJson('/v4/group_open_http_svc/send_group_system_notification', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('创建成功', $res);
    }

    // 发送群普通消息
    public function send_group_message($room_no,$content)
    {
        $data = [
            'GroupId' => (string)$room_no,        // 自定义群组 ID
            'Content' => $content,                // 消息内容
        ];
        $res  = $this->postJson('/v4/group_open_http_svc/send_group_system_notification', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('创建成功', $res);
    }

    /**
     * 转让群主
     * @param $group_chat_id
     * @param $chat_id
     * @return bool
     */
    public function change_owner($group_chat_id, $chat_id)
    {
        $data = [
            'GroupId'          => (string)$group_chat_id,   // 要被转移的群 ID（必填）
            'NewOwner_Account' => (string)$chat_id,         // 新群主 ID（必填）
        ];
        $res  = $this->postJson('/v4/group_open_http_svc/change_group_owner', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('操作成功', $res);
    }

    /**
     * 增加群成员
     * @param $group_chat_id
     * @param array $chat_ids
     * @return bool
     */
    public function add_group_member($group_chat_id, array $chat_ids)
    {
        $MemberList = [];
        foreach ($chat_ids as $value) {
            $MemberList[] = [
                'Member_Account' => $value,// 要添加的群成员ID（必填）
            ];
        }
        $data = [
            'GroupId'    => (string)$group_chat_id,   // 要被转移的群 ID（必填）
            'MemberList' => $MemberList,              // 一次最多添加300个成员
        ];
        $res  = $this->postJson('/v4/group_open_http_svc/add_group_member', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('操作成功', $res);
    }

    /**
     * 解散群组
     * @param $room_no
     * @return bool
     */
    public function destroy_group($room_no)
    {
        $data = [
            'GroupId' => (string)$room_no
        ];
        $res  = $this->postJson('/v4/group_open_http_svc/destroy_group', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('获取成功', $res);
    }

    /**
     * 在群组中发送系统通知
     * @param $room_no
     * @param $type // 雷松：10=点赞通知 20=pk通知
     * @param $content
     * @return bool
     */
    public function send_group_system_notification($room_no, $type, $content)
    {
        $data = [
            'GroupId' => (string)$room_no,
            'Content' => json_encode([
                'type'    => $type,
                'content' => $content,
            ]),
        ];
        $res  = $this->postJson('/v4/group_open_http_svc/send_group_system_notification', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('获取成功', $res);
    }

    /**
     * 封禁用户
     * @param $room_no
     * @param $account
     * @param $time
     * @param $remark
     * @return bool
     */
    public function ban_group_member($room_no, $account, $time, $remark = '违规操作')
    {
        $data = [
            'GroupId'         => (string)$room_no,
            'Members_Account' => [$account],
            'Duration'        => $time, // 封禁时长，单位：秒
            'Description'     => $remark// 封禁信息
        ];
        $res  = $this->postJson('/v4/group_open_http_svc/ban_group_member', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('获取成功', $res);
    }

    /**
     * 解封用户
     * @param $room_no
     * @param $account
     * @return bool
     */
    public function unban_group_member($room_no, $account)
    {
        $data = [
            'GroupId'         => (string)$room_no,
            'Members_Account' => [$account]
        ];
        $res  = $this->postJson('/v4/group_open_http_svc/unban_group_member', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('获取成功', $res);
    }

    // 加入黑名单
    public function black_add($from_user, array $to_users = [])
    {
        $data = [
            'From_Account' => (string)$from_user,
            'To_Account'   => $to_users
        ];
        $res  = $this->postJson('/v4/sns/black_list_add', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('获取成功', $res);
    }
    // 加入黑名单
    public function black_del($from_user, array $to_users = [])
    {
        $data = [
            'From_Account' => (string)$from_user,
            'To_Account'   => $to_users
        ];
        $res  = $this->postJson('/v4/sns/black_list_delete', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('获取成功', $res);
    }

    /**
     * 移除房间
     * @param $room_no
     * @param $account
     * @return bool
     */
    public function delete_group_member($room_no, array $accounts)
    {
        $data = [
            'GroupId'             => (string)$room_no,
            'MemberToDel_Account' => $accounts
        ];
        $res  = $this->postJson('/v4/group_open_http_svc/delete_group_member', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('获取成功', $res);
    }

    /**
     * 禁言 or 解除
     * @param $room_no
     * @param $account
     * @param $time // time = 0 解除
     * @return bool
     */
    public function forbid_send_msg($room_no, $account, $time = 0)
    {
        $data = [
            'GroupId'         => (string)$room_no,
            'Members_Account' => [$account],
            'MuteTime'        => $time
        ];
        $res  = $this->postJson('/v4/group_open_http_svc/forbid_send_msg', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('获取成功', $res);
    }

    /**
     * 获取全部群组
     * @return bool
     */
    public function get_appid_group_list()
    {
        $data = [
            'Limit' => 1000,// 群主 ID
            'Next'  => 0
        ];
        $res  = $this->postJson('/v4/group_open_http_svc/get_appid_group_list', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('获取成功', $res);
    }

    /**
     * 获取直播推流地址
     * @param string $domain 您用来推流的域名
     * @param string $streamName 您用来区别不同推流地址的唯一流名称
     * @param $key 安全密钥
     * @param $time 过期时间 sample 2016-11-12 12:00:00
     * @return string
     */
    public function getLivePushUrl(string $domain,string $streamName,$key = null, $time = null)
    {
        if($key && $time){
            $txTime = strtoupper(base_convert(strtotime($time),10,16));
            //txSecret = MD5( KEY + streamName + txTime )
            $txSecret = md5($key.$streamName.$txTime);
            $ext_str = "?".http_build_query(["txSecret"=> $txSecret, "txTime"=> $txTime]);
        }
        return "rtmp://".$domain."/live/".$streamName . ($ext_str ?? "");
    }

    /**
     * 获取直播播放地址
     * @param string $domain 您用来推流的域名
     * @param string $streamName 您用来区别不同推流地址的唯一流名称
     * @return string
     */
    public function getLivePlayUrl(string $domain,string $streamName)
    {
        return "rtmp://".$domain."/live/".$streamName;
    }

    /**
     * 设置群属性
     * @param int $room_no
     * @param array $attr
     * @return bool
     */
    public function modify_group_attr( $room_no, array $attr)
    {
        $data     = [
            'GroupId'   => (string)$room_no,// 群组 ID
            'GroupAttr' => $attr
        ];
        $res  = $this->postJson('/v4/group_open_http_svc/modify_group_attr', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('获取成功', $res);
    }

    /**
     * 获取群属性
     * @param int $room_no
     */
    public function get_group_attr( $room_no)
    {
        $data     = [
            'GroupId'   => (string)$room_no,// 群组 ID
        ];
        $res  = $this->postJson('/v4/group_open_attr_http_svc/get_group_attr', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('获取成功', $res);
    }

    /**
     * 删除群属性
     * @param int $room_no
     */
    public function delete_group_attr( $room_no,$key)
    {
        $data     = [
            'GroupId'   => (string)$room_no,// 群组 ID
            'GroupAttr' => [[
                'key' => $key,//属性 key
            ]],
        ];
        $res  = $this->postJson('/v4/group_open_http_svc/delete_group_attr', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }

        return $this->success('获取成功', $res);
    }

    // 下载最近消息记录
    public function get_history($MsgTime,$ChatType = 1)
    {
        $data = [
            'ChatType' => $ChatType == 1 ? 'Group' : 'C2C',// 消息类型，C2C 表示单发消息 Group 表示群组消息
            'MsgTime'  => $MsgTime
        ];
        $res  = $this->postJson('/v4/open_msg_svc/get_history', $data);
        if (empty($res['ActionStatus']) || $res['ActionStatus'] != 'OK') {
            return $this->error(!empty($res['ErrorInfo']) ? $res['ErrorInfo'] : 'im error', $res ?? []);
        }
        return $this->success('获取成功', $res);
    }

    //下载远程文件 到指定目录
    public function downloadFile($file_url, $path = '', $save_file_name = '')
    {
        $base_path = "uploads/im_file";
        if ($path) {
            $base_path = "{$base_path}/$path";
        }
        $dir_path = ROOT_PATH . "/public/{$base_path}/" . date('Ymd');
        if (!is_dir($dir_path)) {
            mkdir($dir_path, 0777, true);
        }

        $file = file_get_contents($file_url);

        //传入保存文件的名称
        $filename = $save_file_name ?: pathinfo($file_url, PATHINFO_BASENAME);
        $resource = fopen($dir_path. '/'. $filename, 'w');
        fwrite($resource, $file);
        fclose($resource);
        return $dir_path . '/' . $filename;
    }
    //解压
    public function jieyagz($gz_path = ''){
        $json_path = substr($gz_path,0,-3);
        if ($zp = gzopen($gz_path, 'r')) { // 打开压缩文件
            if ($fp = fopen($json_path, 'w')) { // 打开目标文件
                while (!gzeof($zp)) {
                    fwrite($fp, gzread($zp, 1024 * 512)); // 逐块读取和解压缩后写入
                }
                fclose($fp);
            }
            gzclose($zp);
        }
        return $json_path;
    }

    //读取json并分析,group
    public function readjson_group($json_path = ''){
        $json_content = file_get_contents($json_path);
        $json_content = json_decode($json_content,true);
        $newMsgList = [];
        if(isset($json_content['MsgList']) && !empty($json_content['MsgList'])){
            $MsgList = $json_content['MsgList'];
            foreach($MsgList as $key => $val)
            {
                $MsgBody = isset($val['MsgBody']) ? json_encode($val['MsgBody'],JSON_UNESCAPED_UNICODE) : '';
                $newMsgList[] = [
                    'ClientIP'        => $val['ClientIP'] ?? '',
                    'From_Account'    => $val['From_Account'] ?? '',
                    'GroupId'         => $val['GroupId'] ?? '',
                    'MsgBody'         => $MsgBody,
                    'MsgFromPlatform' => $val['MsgFromPlatform'] ?? '',
                    'MsgSeq'          => $val['MsgSeq'] ?? '',
                    'MsgTimestamp'    => $val['MsgTimestamp'] ?? '',
                ];
            }
        }
        return $newMsgList;
    }

    //读取json并分析,group
    public function readjson_user($json_path = ''){
        $json_content = file_get_contents($json_path);
        $json_content = json_decode($json_content,true);
        $newMsgList = [];
        if(isset($json_content['MsgList']) && !empty($json_content['MsgList'])){
            $MsgList = $json_content['MsgList'];
            foreach($MsgList as $key => $val)
            {
                $MsgBody = isset($val['MsgBody']) ? json_encode($val['MsgBody'],JSON_UNESCAPED_UNICODE) : '';
                $newMsgList[] = [
                    'ClientIP'        => $val['ClientIP'] ?? '',
                    'From_Account'    => $val['From_Account'] ?? '',
                    'To_Account'      => $val['To_Account'] ?? '',
                    'MsgBody'         => $MsgBody,
                    'MsgFromPlatform' => $val['MsgFromPlatform'] ?? '',
                    'MsgRandom'       => $val['MsgRandom'] ?? '',
                    'MsgSeq'          => $val['MsgSeq'] ?? '',
                    'MsgTimestamp'    => $val['MsgTimestamp'] ?? '',
                ];
            }
        }
        return $newMsgList;
    }

    public function get_usersig($user_id){
        return $this->usersig($user_id);
    }

    private function postJson(string $uri, array $params = [], array $header = [])
    {
        $random  = rand(10000000, 99999999);
        $userSig = $this->usersig($this->config['identifier']);
        return CurlUtil::postJson($this->host . $uri . "?sdkappid={$this->config['appid']}&identifier={$this->config['identifier']}&usersig={$userSig}&random={$random}&contenttype=json", $params, $header);
    }

    /**
     * 获取usersig签名-具体操作
     */
    private function userSig($user_id)
    {
        // 获取配置信息
        $userSigObj = new GetUserSig($this->config["appid"], $this->config["key"]);
        return $userSigObj->genUserSig($user_id);
    }
}